/**
 * Copyright (c) 2021-2028, iron.guo 郭成杰 (jiedreams@sina.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.beluga.core.wechat;

import com.alibaba.fastjson.JSONObject;
import com.beluga.core.model.wechat.*;
import com.beluga.core.util.RestUtil;


/**
 * @Author iron.guo
 * @Date 2022/5/2
 * @Description
 */
public class WechatPayApi {

    /**
     * 统一下单
     *
     * @param params 请求参数
     * @return {@link String} 请求返回的结果
     */
    public static String pushOrder(WxBPayUnifiedOrder params) {
        return pushOrder(false, null, params);
    }


    /**
     * 统一下单
     *
     * @param isSandbox 是否是沙盒环境
     * @param params    请求参数
     * @return {@link String} 请求返回的结果
     */
    public static String pushOrder(boolean isSandbox, WxBPayUnifiedOrder params) {
        return pushOrder(isSandbox, null, params);
    }


    /**
     * 统一下单
     *
     * @param isSandbox 是否是沙盒环境
     * @param wxDomain  {@link WechatDomain} 支付 API 接口域名枚举
     * @param params    请求参数
     * @return {@link String} 请求返回的结果
     */
    public static String pushOrder(boolean isSandbox, WechatDomain wxDomain, WxBPayUnifiedOrder params) {
        return execution(getRequestUrl(WeChatApiType.UNIFIED_ORDER, wxDomain, isSandbox), params.toXML());
    }

    /**
     * 订单查询
     *
     * @param params 请求参数
     * @return {@link String} 请求返回的结果
     */
    public static String queryOrder(WxBPayOrderRequest params) {
        return queryOrder(false, null, params);
    }

    /**
     * 订单查询
     *
     * @param isSandbox 是否是沙盒环境
     * @param params    请求参数
     * @return {@link String} 请求返回的结果
     */
    public static String queryOrder(boolean isSandbox, WxBPayOrderRequest params) {
        return execution(getRequestUrl(WeChatApiType.WXORDER_QUERY, null, isSandbox), params.toXML());
    }


    /**
     * 订单查询
     *
     * @param isSandbox 是否是沙盒环境
     * @param params    请求参数
     * @return {@link String} 请求返回的结果
     */
    public static String queryOrder(boolean isSandbox, WechatDomain wxDomain, WxBPayOrderRequest params) {
        return execution(getRequestUrl(WeChatApiType.WXORDER_QUERY, wxDomain, isSandbox), params.toXML());
    }

    /**
     * 关闭订单 /pay/closeorder
     * @param request
     * @return
     */
    public static String closeOrder(WxBPayOrderCloseRequest request) {
        return closeOrder(false, null, request);
    }

    /**
     * 订单查询
     *
     * @param isSandbox 是否是沙盒环境
     * @param params    请求参数
     * @return {@link String} 请求返回的结果
     */
    public static String closeOrder(boolean isSandbox, WxBPayOrderCloseRequest params) {
        return execution(getRequestUrl(WeChatApiType.WXCLOSE_ORDER, null, isSandbox), params.toXML());
    }


    /**
     * 订单查询
     *
     * @param isSandbox 是否是沙盒环境
     * @param params    请求参数
     * @return {@link String} 请求返回的结果
     */
    public static String closeOrder(boolean isSandbox, WechatDomain wxDomain, WxBPayOrderCloseRequest params) {
        return execution(getRequestUrl(WeChatApiType.WXCLOSE_ORDER, wxDomain, isSandbox), params.toXML());
    }



    /**
     * 申请退款
     *
     * @param isSandbox 是否是沙盒环境
     * @param params    请求参数
     * @param certPath  证书文件路径
     * @param certPass  证书密码
     * @return {@link String} 请求返回的结果
     */
    public static String orderRefund(boolean isSandbox, WxBPayRefundRequest params, String certPath, String certPass) {
        return execution(getRequestUrl(WeChatApiType.WXREFUND, null, isSandbox), params.toXML(), certPath, certPass);
    }


    /**
     * 查询退款
     * @param isSandbox 是否是沙盒环境
     * @param params    请求参数
     * @return {@link String} 请求返回的结果
     */
    public static String queryRefund(boolean isSandbox, WxBPayRefundQueryRequest params) {
        return execution(getRequestUrl(WeChatApiType.REFUND_QUERY, null, isSandbox), params.toXML());
    }

    /**
     * 查询退款
     * @param params    请求参数
     * @return {@link String} 请求返回的结果
     */
    public static String queryRefund (WxBPayRefundQueryRequest params) {
        return execution(getRequestUrl(WeChatApiType.REFUND_QUERY, null, false), params.toXML());
    }

    /**
     * 获取接口请求的 URL
     *
     * @param wxApiType {@link WeChatApiType} 支付 API 接口枚举
     * @return {@link String} 返回完整的接口请求URL
     */
    public static String getRequestUrl(WeChatApiType wxApiType) {
        return getRequestUrl(wxApiType, null, false);
    }

    /**
     * 获取接口请求的 URL
     *
     * @param apiType   {@link WeChatApiType} 支付 API 接口枚举
     * @param domain    {@link WechatDomain} 支付 API 接口域名枚举
     * @param isSandBox 是否是沙箱环境
     * @return {@link String} 返回完整的接口请求URL
     */
    public static String getRequestUrl(WeChatApiType apiType, WechatDomain domain, boolean isSandBox) {
        if (domain == null) {
            domain = WechatDomain.CHINA;
        }
        return domain.getDomain()
                .concat(isSandBox ? WeChatApiType.SAND_BOX.getType() : "")
                .concat(apiType.getType());
    }

    /**
     * 发起请求
     *
     * @param apiUrl 接口 URL
     *               通过 {@link WechatPayApi#getRequestUrl(WeChatApiType)}
     *               或者 {@link WechatPayApi#getRequestUrl(WeChatApiType, WechatDomain, boolean)} 来获取
     * @param xml 接口请求报文
     * @return {@link JSONObject} 请求返回的结果
     */
    public static String execution(String apiUrl, String xml) {
        return RestUtil.post(apiUrl,xml);
    }

    /**
     * 发起请求
     *
     * @param apiUrl   接口 URL
     *                 通过 {@link WechatPayApi#getRequestUrl(WeChatApiType)}
     *                 或者 {@link WechatPayApi#getRequestUrl(WeChatApiType, WechatDomain, boolean)} 来获取
     * @param xml   接口请求报文
     * @param certPath 证书文件路径
     * @param certPass 证书密码
     * @return {@link String} 请求返回的结果
     */
    public static String execution(String apiUrl, String xml, String certPath, String certPass) {
        return RestUtil.postSsl(apiUrl, xml, certPath, certPass);
    }


}
